﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace WHControlLib.CommonHelpers
{
    public  class ReflectionHelper
    {
        
        /// <summary>
     ///  实例化反射对象
     /// </summary>
     /// <param name="t">如果类型为null，就根据对象获取类型</param>
     /// <param name="obj">如果对象为null，就根据类型实例化对象</param>
        static void JudgeType(ref Type t, ref object obj, ref BindingFlags flags, bool isPublic, bool isStatic)
        {
            if (t != null)
            {
                obj = Activator.CreateInstance(t);
            }
            else
            {
                t = obj.GetType();
            }
            flags = (isStatic ? BindingFlags.Static : BindingFlags.Instance) | (isPublic ? BindingFlags.Public : BindingFlags.NonPublic);
        }

        /// <summary>
        /// 获取对象的属性或者字段的值
        /// </summary>
        /// <param name="t">如果类型为null，就根据对象获取类型</param>
        /// <param name="obj">如果对象为null，就根据类型实例化对象</param>
        /// <param name="name">属性或者字段的名称</param>
        /// <param name="isPublic">是否是public修饰符修饰的</param>
        /// <param name="isStatic">是否是静态的</param>
        /// <returns>返回字段或者属性的值</returns>
        public static object GetFieldOrProperty(Type t, object obj, string name, bool isPublic, bool isStatic)
        {
            BindingFlags flags = BindingFlags.Default;
            JudgeType(ref t, ref obj, ref flags, isPublic, isStatic);
            FieldInfo fieldInfo = t.GetField(name, flags);
            if (fieldInfo == null)
            {
                PropertyInfo propertyInfo = t.GetProperty(name, flags);
                if (propertyInfo != null)
                {
                    return propertyInfo.GetValue(obj, null);
                }
                return null;
            }
            return fieldInfo.GetValue(obj);
        }

        /// <summary>
        /// 反射执行对象的方法
        /// </summary>
        /// <param name="t">如果类型为null，就根据对象获取类型</param>
        /// <param name="obj">如果对象为null，就根据类型实例化对象</param>
        /// <param name="methodName">方法名称</param>
        /// <param name="parameters">方法参数</param>
        /// <param name="isPublic">是否是public修饰符修饰的</param>
        /// <param name="isStatic">是否是静态的</param>
        public static void ExecuteMethod(Type t, object obj, string methodName, object[] parameters, bool isPublic, bool isStatic)
        {
            BindingFlags flags = BindingFlags.Default;
            JudgeType(ref t, ref obj, ref flags, isPublic, isStatic);
            MethodInfo methodInfo = t.GetMethod(methodName, flags);
            if (methodInfo != null)
            {
                methodInfo.Invoke(obj, parameters);
            }
        }

        /// <summary>
        /// 得到属性或者字段或者方法的特性
        /// </summary>
        /// <param name="t">如果类型为null，就根据对象获取类型</param>
        /// <param name="obj">如果对象为null，就根据类型实例化对象</param>
        /// <param name="name">名称</param>
        /// <param name="isPublic">是否是public修饰符修饰的</param>
        /// <param name="isStatic">是否是静态的</param>
        /// <returns></returns>
        public static object[] GetCustomAttributes(Type t, object obj, string name, bool isPublic, bool isStatic)
        {
            BindingFlags flags = BindingFlags.Default;
            JudgeType(ref t, ref obj, ref flags, isPublic, isStatic);
            MethodInfo methodInfo = t.GetMethod(name, flags);
            if (methodInfo != null)
            {
                return methodInfo.GetCustomAttributes(false);
            }
            else
            {
                FieldInfo fieldInfo = t.GetField(name, flags);
                if (fieldInfo != null)
                {
                    return fieldInfo.GetCustomAttributes(false);
                }
                else
                {
                    PropertyInfo propertyInfo = t.GetProperty(name, flags);
                    if (propertyInfo != null)
                    {
                        return propertyInfo.GetCustomAttributes(false);
                    }
                    return null;
                }
            }
        }

        /// <summary>
        /// 加载程序集，并实例化对象
        /// </summary>
        /// <param name="dllPath">程序集路径（绝对路径）</param>
        /// <param name="index">为-1，表示要实例化所有对象，不为-1，表示要实例化索引为index的对象</param>
        /// <param name="objList">输出实例化的对象</param>
        /// <returns>返回所有类型</returns>
        public static Type[] GetTypes(string dllPath, int index, ref List<object> objList)
        {
            objList = new List<object>();
            Type[] t;
            object obj;
            Assembly assembly = Assembly.LoadFile(dllPath);
            t = assembly.GetTypes();
            if (index == -1)
            {
                foreach (var item in t)
                {
                    obj = Activator.CreateInstance(item);
                    objList.Add(obj);
                }
            }
            else
            {
                obj = Activator.CreateInstance(t[index]);
                objList.Add(obj);
            }
            return t;
        }
    }
}
